package org.walkerljl.commons.util;


import org.walkerljl.commons.exception.AppException;
import org.walkerljl.commons.log.Logger;
import org.walkerljl.commons.log.LoggerFactory;
import org.walkerljl.commons.ump.AlarmProvider;

/**
 * 跟踪处理工具
 *
 * @author lijunlin
 */
public class TraceUtils {

    private static final Logger LOGGER = LoggerFactory.getLogger(TraceUtils.class);
    private static AlarmProvider alarmProvider;

    /**
     * 跟踪异常
     *
     * @param messagePrefix 消息前缀
     */
    public static void traceException(String messagePrefix) {
        TraceUtils.traceException(messagePrefix, null, null, null);
    }

    /**
     * 跟踪异常
     *
     * @param messagePrefix 消息前缀
     */
    public static void traceExceptionQuietly(String messagePrefix) {
        TraceUtils.traceExceptionQuietly(messagePrefix, null, null, null);
    }

    /**
     * 跟踪异常
     *
     * @param messagePrefix 消息前缀
     * @param e
     */
    public static void traceException(String messagePrefix, Throwable e) {
        TraceUtils.traceException(messagePrefix, null, e, null);
    }

    /**
     * 跟踪异常
     *
     * @param messagePrefix 消息前缀
     * @param e
     */
    public static void traceExceptionQuietly(String messagePrefix, Throwable e) {
        TraceUtils.traceExceptionQuietly(messagePrefix, null, e, null);
    }

    /**
     * 跟踪异常
     *
     * @param messagePrefix 消息前缀
     * @param request       请求
     * @param e             异常对象
     */
    public static void traceException(String messagePrefix, String request, Throwable e) {
        TraceUtils.traceException(messagePrefix, request, e, null);
    }

    /**
     * 跟踪异常
     *
     * @param messagePrefix 消息前缀
     * @param request       请求
     * @param e             异常对象
     */
    public static void traceExceptionQuietly(String messagePrefix, String request, Throwable e) {
        TraceUtils.traceExceptionQuietly(messagePrefix, request, e, null);
    }

    /**
     * 跟踪异常
     *
     * @param messagePrefix
     * @param request
     * @param e
     * @param alarmKey
     */
    public static void traceException(String messagePrefix, String request, Throwable e, String alarmKey) {
        TraceUtils.doTraceException(messagePrefix, request, e, alarmKey);
        //rethrow the exception
        if (e instanceof RuntimeException) {
            throw (RuntimeException) e;
        } else {
            throw new Error(e.getMessage(), e);
        }
    }

    /**
     * 跟踪异常
     *
     * @param messagePrefix
     * @param request
     * @param e
     * @param alarmKey
     */
    public static void traceExceptionQuietly(String messagePrefix, String request, Throwable e, String alarmKey) {
        TraceUtils.doTraceException(messagePrefix, request, e, alarmKey);
    }

    /**
     * 跟踪异常
     *
     * @param messagePrefix
     * @param request
     * @param e
     * @param alarmKey
     */
    private static void doTraceException(String messagePrefix, String request, Throwable e, String alarmKey) {
        try {
            if (e != null && e instanceof AppException) {
                TraceUtils.warn(messagePrefix, request, (e == null ? "NULL" : e.getMessage()));
            } else {
                String message = TraceUtils.wrapTraceMessage(messagePrefix, request, (e == null ? "NULL" : e.getMessage()));
                LOGGER.error(message, e);
                if (alarmProvider != null) {
                    if (StringUtils.isEmpty(alarmKey)) {
                        alarmProvider.alarm(message);
                    } else {
                        alarmProvider.alarm(alarmKey, message);
                    }
                }
            }
        } catch (Exception inner) {
            LOGGER.error("Fail to process exception:" + inner.getMessage(), inner);
        }
    }

    /**
     * 记录INFO级别日志 <li>log4j支持</li>
     *
     * @param messagePrefix 消息前缀
     * @param request       请求
     * @param response      响应
     */
    public static void info(String messagePrefix, String request, String response) {
        if (LOGGER.isInfoEnabled()) {
            LOGGER.info(TraceUtils.wrapTraceMessage(messagePrefix, request, response));
        }
    }

    /**
     * 记录WARN级别日志 <li>log4j支持</li>
     *
     * @param messagePrefix 消息前缀
     * @param request       请求
     * @param response      响应
     */
    public static void warn(String messagePrefix, String request, String response) {
        if (LOGGER.isWarnEnabled()) {
            LOGGER.warn(TraceUtils.wrapTraceMessage(messagePrefix, request, response));
        }
    }

    /**
     * 包装跟踪消息
     *
     * @param messagePrefix 消息前缀
     * @param request       请求
     * @param response      响应
     * @return
     */
    public static String wrapTraceMessage(String messagePrefix, String request, String response) {
        return String.format("%s: Request->%s; Response->%s", messagePrefix, request, response);
    }

    /**
     * 将对象列表转换成String
     *
     * @param objects 对象列表
     * @return
     */
    public static String toString(Object... objects) {
        if (objects == null || objects.length == 0) {
            return "";
        }
        return JSONUtils.toJSONString(objects);
    }

    /**
     * 设置报警器
     * @param alarmProvider
     */
    public static void setAlarmProvider(AlarmProvider alarmProvider) {
        TraceUtils.alarmProvider = alarmProvider;
    }
}
